package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.common.R;
import com.itheima.dao.CategoryDao;
import com.itheima.dao.DishDao;
import com.itheima.dao.DishFlavorDao;
import com.itheima.pojo.*;
import com.itheima.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

@Slf4j
//@Service
public class DishServiceImpl extends ServiceImpl<DishDao, Dish> implements DishService {
    @Autowired
    private DishDao dishDao;
    @Autowired
    private DishFlavorDao dishFlavorDao;
    @Autowired
    private CategoryDao categoryDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public Page pageSelect(Integer page, Integer pageSize, String name) {
        //构造分页构造器对象
        Page<Dish> dishPage = new Page<>(page,pageSize);
        Page<DishDto> dishDtoPage = new Page<>();
        //条件构造器
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        //添加过滤条件
        lqw.like(name != null && !"".equals(name),Dish::getName,name);
        //添加排序条件
        lqw.orderByAsc(Dish::getSort);
        //执行分页查询
        dishDao.selectPage(dishPage,lqw);
        //给dishDtoPage的total属性赋值
        dishDtoPage.setTotal(dishPage.getTotal());
        List<Dish> dishes = dishPage.getRecords();
        List<DishDto> dishDtos = new ArrayList<>();
        for (Dish dish : dishes) {
            DishDto dishDto = new DishDto();
            Category category = categoryDao.selectById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());
            //对象拷贝
            BeanUtils.copyProperties(dish,dishDto);
            dishDtos.add(dishDto);
        }
        dishDtoPage.setRecords(dishDtos);
        return dishDtoPage;
    }

    @Override
    @Transactional
    public void saveDish(DishDto dishDto) {
        //存菜品数据
        dishDao.insert(dishDto);
        //清理菜品缓存
        redisTemplate.delete("dish_"+dishDto.getCategoryId());
        //存菜品口味数据
        List<DishFlavor> flavors = dishDto.getFlavors();
        if (flavors != null && flavors.size() > 0){
            //Mybatis-Plus自动开启了主键返回，直接获取菜品Id
            Long dishId = dishDto.getId();
            for (DishFlavor flavor : flavors) {
                flavor.setDishId(dishId);
                dishFlavorDao.insert(flavor);
            }
        }
    }

    @Override
    public DishDto getDishDto(Long id) {
        Dish dish = dishDao.selectById(id);
        LambdaQueryWrapper<DishFlavor> lqw = new LambdaQueryWrapper<>();
        lqw.eq(DishFlavor::getDishId,id);
        List<DishFlavor> dishFlavors = dishFlavorDao.selectList(lqw);
        DishDto dishDto = new DishDto();
        BeanUtils.copyProperties(dish,dishDto);
        dishDto.setFlavors(dishFlavors);
        return dishDto;
    }

    @Override
    public void updateDishDto(DishDto dishDto) {
        //修改菜品
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDto,dish);
        dishDao.updateById(dish);
        //清理菜品缓存
        redisTemplate.delete("dish_"+dishDto.getCategoryId());
        //修改菜品口味
        Long dishId = dishDto.getId();
        LambdaQueryWrapper<DishFlavor> lqw = new LambdaQueryWrapper<>();
        lqw.eq(DishFlavor::getDishId,dishId);
        //先删除原有菜品口味数据
        dishFlavorDao.delete(lqw);
        //再存菜品口味数据
        List<DishFlavor> flavors = dishDto.getFlavors();
        if (flavors != null && flavors.size() > 0){
            for (DishFlavor flavor : flavors) {
                flavor.setDishId(dishId);
                dishFlavorDao.insert(flavor);
            }
        }
    }

    @Override
    public void updateStatus(Integer status, List<Long> ids) {
        LambdaUpdateWrapper<Dish> luw = new LambdaUpdateWrapper<>();
        luw.set(Dish::getStatus,status);
        luw.in(Dish::getId,ids);
        Dish dish = new Dish();
        dishDao.update(dish,luw);
    }

    @Override
    public R deleteByIds(List<Long> ids) {
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dish::getStatus,1);
        lqw.in(Dish::getId,ids);
        Integer count = dishDao.selectCount(lqw);
        if (count > 0){
            return R.error("菜品在售，无法删除");
        }
        dishDao.deleteBatchIds(ids);
        return R.success("删除成功");
    }

    @Override
    public List<DishDto> selectDishByCategoryId(Long categoryId, String name) {

        //1.先从redis缓存中获取数据，缓存中有数据, 直接返回
        List<DishDto> dishDtos = (List<DishDto>) redisTemplate.opsForValue().get("dish_" + categoryId);
        if (dishDtos != null){
            return dishDtos;
        }
        //2.缓存中没有，再查询数据库，并将数据库查询结果，缓存在redis，并设置过期时间
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(categoryId != null ,Dish::getCategoryId,categoryId);
        //添加条件，查询状态为1（起售状态）的菜品
        lqw.eq(Dish::getStatus,1);
        lqw.like(name != null && !"".equals(name),Dish::getName,name);
        //添加排序条件
        lqw.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        //查询菜品
        List<Dish> dishes = dishDao.selectList(lqw);
        dishDtos = new ArrayList<>();
        for (Dish dish : dishes) {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            LambdaQueryWrapper<DishFlavor> lqw1 = new LambdaQueryWrapper<>();
            lqw1.eq(DishFlavor::getDishId,dish.getId());
            List<DishFlavor> dishFlavors = dishFlavorDao.selectList(lqw1);
            dishDto.setFlavors(dishFlavors);
            dishDtos.add(dishDto);
        }
        redisTemplate.opsForValue().set("dish_"+categoryId,dishDtos);
        return dishDtos;
    }
}
